//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.
// 			VisualNovelToolkit		     /_/_/_/_/_/_/_/_/_/.
// Copyright ©2013 - Sol-tribe.	/_/_/_/_/_/_/_/_/_/.
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using ViNoToolkit;

/// <summary>
/// TextBox UI Component.
/// </summary>
[ System.Serializable]
[ AddComponentMenu( "ViNo/UI/TextBox" ) ]
public class ViNoTextBox : MonoBehaviour{
	public ViNoTextEventListener textEventListener;
	public GameObject backGround;
	public bool ClearMessageAtAwake;
	public Blink blink;

	// Text Animation.
	public bool useTextAfterEffect;

	public AnimationNode textDisplayEffect;	// For example , attach a AnimationNode with Fade in Effect.
	public AnimationNode textAfterEffect;	// For example , attach a AnimationNode with Fade out Effect.

	[ Range( 10 , 200 ) ]
	public int m_TextSpeed = 100;

	public bool wrapText;
	public int wrapEvery = 22;	// default value.
			
	[ HideInInspector ]public bool playAtStart;
	[ HideInInspector ][ SerializeField ] private string m_Text;
	[ HideInInspector ][ SerializeField ] private float m_TimeElapsed = 0f;
	[ HideInInspector ][ SerializeField ] public float m_WaitTime = 0.1f;
	
	private Vector3 m_InitialPos;
	private int m_StartIndex = 0;
	private int m_CurrLength = 0;
	private bool m_ReachedEnd;
	private bool m_Update;
	private ColorPanel m_Panel;

	//******************* Properties ****************************.

	public int startIndex{
		set{
			m_StartIndex = value;						
		}
		get{
			return m_StartIndex;
		}
	}
		
	/// <summary>
	/// The text of All.
	/// </summary>
	/// <value>
	/// The text.
	/// </value>
	public string text{
		get{	
			return m_Text;
		}
		set{
			m_Text = value;
		}
	}	
	
	/// <summary>
	/// Gets or sets the text speed Percentage 100% is Normal Speed.
	/// </summary>
	/// <value>
	/// The text speed.
	/// </value>
	public int textSpeed{
		get{				
			return (int)( 1f / m_WaitTime );
		}
		set{
			m_WaitTime = 1f/(float)value;
		}
	}
	
	/// <summary>
	/// The Text to be Shown in a TextView.
	/// </summary>
	/// <value>
	/// The text shown.
	/// </value>
	public string textShown{
		get{ 
			if( m_CurrLength < m_Text.Length ){
				if( m_CurrLength == 1 ){
					if( m_Text[ 0 ].Equals( '[' ) ){
						StripTag();
					}
				}
				if( m_CurrLength - 1 >= 0 ){
					if( m_Text[ m_CurrLength - 1 ].Equals( '[' ) ){
						StripTag();
					}
				}
				return m_Text.Substring( m_StartIndex , m_CurrLength );
			}
			else{
				if( m_Update ){
					if( textEventListener != null) {
						textEventListener.OnDisplayedText( );
					}									
				}
				m_Update = false;
				m_ReachedEnd = true;
				return m_Text;	
			}
		}	
	}
		
	public bool reachedEnd{ 
		get{
			 return m_ReachedEnd;
		  }
	}		
	
	public int currentTextLength{
		get{
			 return m_CurrLength;
		}
	}	

	public ColorPanel panel{
		get { return m_Panel; }
	}

	//***********************************************.	

	// param hash is attributes.
	public void ChangeProperty( Hashtable param ){
		textEventListener.OnPropertyChange( param );
	}

	public void ResetFont(){
		textEventListener.ResetFont();
	}

	void Awake(){
		if( ClearMessageAtAwake ){
			ClearMessage();
		}
		m_Panel = GetComponent<ColorPanel>();
	}

	void Start(){		
		textSpeed = m_TextSpeed;
	}
		
	// Update is called once per frame
	void Update(){				
		if( ! m_Update ){
			return;	
		}
		
		if( ! reachedEnd ){
			if( Process( Time.deltaTime * ViNoConfig.prefsTextSpeed ) ){
				m_CurrLength++;				
				if( textEventListener != null) {
					textEventListener.OnUpdateText( textShown );
				}
			}
		}
	}

	public void NextMessage(){
		if( blink != null ){
			blink.DontShow();
		}

		if( ! ViNo.isLockNextMessage ){
			if( useTextAfterEffect ){
				if( ! reachedEnd ){		
					ViNo.NextMessage();
				}
				else{
					DoTextAfterEffect();
				}
			}
			else{
				ViNo.NextMessage();				
			}
		}		
	}

	public void ActivateBackground( bool t ){
		if( backGround != null ){
			backGround.SetActive( t );	
		}
	}
		
	/// <summary>
	/// Sets the text.
	/// </summary>
	/// <param name='text'>
	/// Text.
	/// </param>
	public void SetText( string text  ){
		if( textEventListener != null) {
			textEventListener.OnTextSet( text );
		}
	}

	/// <summary>
	/// Initialize the specified message.
	/// </summary>
	/// <param name='message'>
	/// Message.
	/// </param>
	public void Initialize( string message ){
		text = message;
						
		if( blink != null ){
			blink.DontShow();
		}			
		// Init.
		m_Update = true;
		m_TimeElapsed = 0f;			
		startIndex = 0;
		m_CurrLength = 0;
		m_ReachedEnd = false;		
	}

	/// <summary>
	/// Append the specified message.
	/// </summary>
	/// <param name='message'>
	/// Message.
	/// </param>
	public void Append( string message  ){
		if( blink != null ){
			blink.DontShow();
		}

		if( wrapText ){
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			int counter = 0;
			for(int i=0;i<message.Length;i++){
				sb.Append( message[ i ] );
				counter++;
				if( counter > wrapEvery ){
					counter = 0;
					sb.Append( System.Environment.NewLine );
				}
			}
			text += sb.ToString();
		}
		else{
			text += message;
		}

		if( ! m_Update ){
			if( textEventListener != null) {
				textEventListener.OnStartMessage();
			}		
		}
		
		m_Update = true;
		m_TimeElapsed = 0f;			

		m_ReachedEnd = false;			
		
		if( textEventListener != null) {
			textEventListener.OnAppend( message );
		}		
	}
			
	/// <summary>
	/// Process the specified dt.
	/// </summary>
	/// <param name='dt'>
	/// If set to <c>true</c> dt.
	/// </param>
	public bool Process( float dt ){
		m_TimeElapsed += dt;
		if( m_TimeElapsed > m_WaitTime ){
			textSpeed = m_TextSpeed;
			m_TimeElapsed = 0f;			
			return true;
		}
		else{
			return false;	
		}
	}
	
	/// <summary>
	/// Clears the message.
	/// </summary>
	public void ClearMessage(){
		Initialize( "" );
		m_Update = false;
		if( textEventListener != null) {
			textEventListener.OnUpdateText( "" );
		}
	}
		
	public void CommitChanges(){
		if( textEventListener != null) {
			textEventListener.CommitChanges();
		}		
	}

	/// <summary>
	/// Display the text quick.
	/// </summary>
	public void DispTextQuick(){
		m_CurrLength = m_Text.Length;
		string text = textShown;	// Get Text and Reached end soon.	
		
		if( textEventListener != null) {
			textEventListener.OnUpdateText( text );
		}
	}

	public void DoTextDisplayEffect(){
		if( textDisplayEffect != null ){
			textDisplayEffect.Preview();
		}		
	}

	public void DoTextAfterEffect(){
		StartCoroutine( "TextAfterEffectAndNextMessage" );		
	}

	IEnumerator TextAfterEffectAndNextMessage( ){		
		ViNo.LockNextMessage();

		if( textAfterEffect != null ){
			textAfterEffect.Preview();
		}

		// Wait Until the Text After Effect is Finished.
		if( textAfterEffect != null ){			
			yield return new WaitForSeconds( textAfterEffect.duration/1000f );
		}
		else{
			yield return new WaitForSeconds( 0.001f );
		}

		ViNo.UnlockNextMessage();
		ViNo.NextMessage();
	}				

	//*********** Getter *****************.

	public string GetBeginColorTag( Color col ){
		return textEventListener.GetBeginColorTag( col );
	}

	public string GetEndColorTag(){
		return textEventListener.GetEndColorTag();
	}

	public bool IsUpdate(){
		return m_Update;
	}

	private void StripTag(){
		while( ! m_Text[ m_CurrLength - 1 ].Equals( ']') ){
			m_CurrLength++;
		}
		m_CurrLength++;
	}

}

